import $ from "jquery";
import EventCenter from "./event_center";
import AssetsConfig from "./assets_config";
import AssetTypes from "./asset_types";
import System from "./system";
import Event from "./event";
import ProgressEvent from "./progress_event";
import ErrorEvent from "./error_event";
import Base64js from "./base64_js";

class AssetItem {
  constructor(e?, y?) {
    if (arguments.length <= 0) return;
    let t = this;
    t.referenceCount = 1;
    let n = /:(\d+)$/;
    if (n.test(e)) {
      let i = e.match(n);
      t.sliceCount = parseInt(i[1], 10);
      let s = e.split(":");
      (s = s.slice(0, s.length - 1)), (e = s.join(":"));
    } else t.sliceCount = 1;
    let o = /^\w+\|/;
    if (o.test(e)) {
      let u = e.split("|"),
        a = u.slice(1),
        f = a.join("|");
      (u = u.slice(0, 1)), (u = u.concat(f)), (t.type = u[0]), (t.uri = u[1]);
    } else {
      let l = /\.(\w+)$/,
        c = e.match(l);
      if (c != null && c.length >= 2) {
        let h = c[1].toLowerCase();
        switch (h) {
          case "jpg":
          case "jpeg":
          case "gif":
          case "png":
            t.type = AssetTypes.IMAGE;
            break;
          case "json":
            t.type = AssetTypes.JSON;
            break;
          case "html":
          case "htm":
            t.type = AssetTypes.HTML;
            break;
          case "mp3":
          case "ogg":
            t.type = AssetTypes.SOUND;
            break;
          case "xml":
            t.type = AssetTypes.XML;
            break;
          default:
            t.type = AssetTypes.TEXT;
        }
      } else t.type = AssetTypes.TEXT;
      t.uri = e;
    }
    t.configLoadURL(t.uri),
      (t.loaded = !1),
      (t.asset = null),
      (t.bytesLoaded = 0),
      (t.bytesTotal = 0);
  }
  referenceCount = 0;
  startLoadTS = null;
  endLoadTS = null;
  failCount = 0;
  MAX_FAIL_COUNT = 10;
  uri = null;
  loadURL = null;
  type = null;
  loading = !1;
  loaded = !1;
  sliceCount = 1;
  bytesLoaded = 0;
  bytesTotal = 0;
  loadPercent() {
    let e = this,
      t = 0;
    return (
      e.loaded
        ? (t = 1)
        : e.bytesTotal == 0
        ? (t = 0)
        : (t = e.bytesLoaded / e.bytesTotal),
      t
    );
  }
  asset = null;
  configLoadURL(e) {
    let t = this,
      r = /^abs:/gi,
      i = /^https*/gi,
      s = /^\//gi,
      o = /^\.\//gi;
    r.test(e)
      ? (t.loadURL = e.slice(4, e.length))
      : i.test(e) || s.test(e) || o.test(e)
      ? (t.loadURL = e)
      : (t.loadURL = AssetsConfig.baseURI + e);
  }
  load() {
    let e = this;
    (e.loading = !0), (e.startLoadTS = new Date().getTime);
    let t = e[e.type + "Loader"];
    t.call(e);
  }
  assetPaths = null;
  assetImages = null;
  multipleAssetLoaded(e, n) {
    let r = this;
    (r.assetPaths = e),
      (r.assetImages = n),
      (r.loaded = !0),
      (r.loading = !1),
      (r.endLoadTS = new Date().getTime());
    let i = new Event(r, Event.LOAD);
    EventCenter.dispatchEvent(i);
  }
  assetLoaded(e) {
    let n = this;
    (n.asset = e),
      (n.loaded = !0),
      (n.loading = !1),
      (n.endLoadTS = new Date().getTime());
    let r = new Event(n, Event.LOAD);
    EventCenter.dispatchEvent(r);
  }
  assetLoadError(e, n) {
    let r = this;
    r.failCount++;
    if (r.failCount < r.MAX_FAIL_COUNT)
      System.log(
        "Fail to fetch data from url: " +
          r.loadURL +
          ". status: " +
          e +
          " des: " +
          n +
          ". Will retry in 150ms. Fail count:" +
          r.failCount
      ),
        setTimeout(function () {
          r.load();
        }, 150);
    else {
      let s =
        "Fail to fetch data from url: " +
        r.loadURL +
        ". status: " +
        e +
        " des: " +
        n +
        ". Try count:" +
        r.failCount;
      System.log(s);
      let o = new Error(s);
      EventCenter.dispatchEvent(new ErrorEvent(r, o));
    }
  }
  loadWithXHR(n, r, s, u?) {
    let a = this;
    (r = typeof r == "string" ? r : "text"),
      (s = typeof s == "boolean" ? s : !0),
      (u = typeof u == "string" ? u : "get"),
      $.ajax({
        url: a.loadURL,
        dataType: r,
        async: !0,
        cache: s,
        type: u,
        success: function (e, t) {
          t == "success" ? n(e, t) : a.assetLoadError(t, "Unknown Error.");
        },
        xhr: function () {
          let e = System.nativeXHR();

          return (
            (e.onprogress = function (e) {
              (a.bytesTotal = e.total), (a.bytesLoaded = e.loaded);
              let n = new ProgressEvent(a, a.loadPercent());
              EventCenter.dispatchEvent(n);
            }),
            e
          );
        },
        error: function (e, t, n) {
          a.assetLoadError(t, n);
        },
      });
  }
  imageLoader() {
    let t = this,
      n: any = $("<img/>");
    (n[0].crossOrigin = ""),
      n.width("auto").height("auto").css("display", "inline-block"),
      n.bind("load", function () {
        n.removeAttr("style"), t.assetLoaded(n[0]);
      }),
      n.bind("error", function () {
        t.assetLoadError("error", "Unknown error.");
      }),
      n.attr("src", t.loadURL);
  }
  textLoader() {
    let e = this,
      t = function (t) {
        e.assetLoaded(t);
      };
    e.loadWithXHR(t, "text", !1);
  }
  jsonLoader() {
    let e = this,
      t = function (t) {
        e.assetLoaded(t);
      };
    e.loadWithXHR(t, "json", !1);
  }
  htmlLoader  () {
    let t = this,
      n = function (n) {
        let r = $(n),
          i = r.find("div[pre-load]");
        i.length > 0
          ? t.assetLoaded(r.find("> div[pre-load]"))
          : t.assetLoaded(r);
      };
    t.loadWithXHR(n, "html", !0);
  }
  xmlLoader() {
    let t = this,
      n = function (n) {
        t.assetLoaded($(n).find("> *"));
      };
    t.loadWithXHR(n, "xml", !0);
  }
  soundLoader() {
    let t = this,
      n: any = $("<audio></audio>");
    n.attr("src", t.loadURL),
      n.bind("canplaythrough suspend", function () {
        t.assetLoaded(n[0]), n.unbind();
      }),
      n.bind("error", function () {
        t.assetLoadError("error", "Unknown error."), n.unbind();
      }),
      n[0].load();
  }
  axeLoader() {
    let e = this,
      n = function (t) {
        let n = t.currentTarget,
          r = n.response,
          i = new DataView(r),
          s = 0,
          o = [],
          u = [],
          f = [];
        while (s < i.byteLength) {
          let l = i.getUint32(s, !1);
          s += 4;
          let c = "";
          for (let h = 0; h < l; h++) {
            let p = i.getUint32(s, !1);
            (s += 4), (c += String.fromCharCode(p));
          }
          let d = i.getUint32(s, !1);
          s += 4;
          let v = new Uint8Array(r, s, d);

          (s += d), o.push(c), f.push(v);
        }
        let m = 0,
          g = window.URL || window.webkitURL,
          y = function () {
            if (m >= f.length) e.multipleAssetLoaded(o, u);
            else {
              let t = f[m],
                n = document.createElement("img");
              n.onload = function (e: any) {
                try {
                  g.revokeObjectURL(e.currentTarget.src);
                } catch (t) {}
                u.push(n), (m += 1), y();
              };
              try {
                n.src = g.createObjectURL(new Blob([t]));
              } catch (r) {
                let i = o[m].substr(o[m].length - 3, 3).toLowerCase(),
                  s;
                i == "jpg" || i == "jpeg"
                  ? (s = "data:image/jpeg;base64,")
                  : i == "png"
                  ? (s = "data:image/png;base64,")
                  : i == "gif" && (s = "data:image/gif;base64,"),
                  (n.src = s + Base64js.fromByteArray(t));
              }
            }
          };
        y();
      },
      r = System.nativeXHR();
    (r.responseType = "arraybuffer"),
      r.open("get", e.loadURL, !0),
      (r.onload = n),
      (r.onprogress = function (n) {
        (e.bytesTotal = n.total), (e.bytesLoaded = n.loaded);
        let r = new ProgressEvent(e, e.loadPercent());
        EventCenter.dispatchEvent(r);
      }),
      (r.onerror = function (t, n) {
        e.assetLoadError(t, n);
      }),
      r.send();
  }
}
export default AssetItem;
